package de.slothsoft.android4swing;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

public class DebugAndroidResourceBundle extends AndroidResourceBundle {

    public List<Warning> warnings;

    public DebugAndroidResourceBundle(String bundlePath, Locale locale) {
	super(bundlePath, locale);
    }

    @Override
    Map<String, String> fetchEntries(String bundlePath) throws IOException {
	Map<String, String> result = fetchBaseBundle(bundlePath);
	if (this.locale != null) {
	    Map<String, String> localizedResult = fetchBundle(bundlePath);
	    if (localizedResult != null) {
		checkMissingTranslations(result, localizedResult);
		checkTranslationsToMuch(result, localizedResult);
		result.putAll(localizedResult);
	    }
	}
	return result;
    }

    @Override
    Map<String, String> fetchBundle(String bundlePath) throws IOException {
	Map<String, String> result = super.fetchBundle(bundlePath);
	if (result == null) {
	    addMissingBundleWarning(bundlePath);
	}
	return result;
    }

    private void addMissingBundleWarning(String bundlePath) {
	getWarnings().add(new Warning(WarningType.MISSING_BUNDLE, bundlePath, this.locale.getDisplayLanguage()));
    }

    private void checkMissingTranslations(Map<String, String> entries, Map<String, String> localizedEntries) {
	Set<String> missingTranslationKeys = new HashSet<>(entries.keySet());
	missingTranslationKeys.removeAll(localizedEntries.keySet());
	addMissingFileWarning(missingTranslationKeys);
    }

    private void addMissingFileWarning(Set<String> missingTranslationKeys) {
	for (String missingTranslationKey : missingTranslationKeys) {
	    getWarnings().add(
		    new Warning(WarningType.MISSING_TRANSLATION, missingTranslationKey, this.locale
			    .getDisplayLanguage()));
	}
    }

    private void checkTranslationsToMuch(Map<String, String> entries, Map<String, String> localizedEntries) {
	Set<String> translationsToMuch = new HashSet<>(localizedEntries.keySet());
	translationsToMuch.removeAll(entries.keySet());
	addTranslationsToMuchWarning(translationsToMuch);
    }

    private void addTranslationsToMuchWarning(Set<String> translationsToMuch) {
	for (String translationToMuch : translationsToMuch) {
	    getWarnings().add(
		    new Warning(WarningType.TRANSLATION_TO_MUCH, translationToMuch, this.locale.getDisplayLanguage()));
	}
    }

    public synchronized List<Warning> getWarnings() {
	if (this.warnings == null) {
	    this.warnings = new ArrayList<>();
	}
	return this.warnings;
    }

    /*
	 * 
	 */

    public static class Warning {

	final WarningType type;
	final Object[] arguments;

	public Warning(WarningType type, Object... arguments) {
	    this.type = type;
	    this.arguments = arguments;
	}

	public WarningType getType() {
	    return this.type;
	}

	public Object[] getArguments() {
	    return this.arguments;
	}

	public String getMessage() {
	    return MessageFormat.format(Messages.getString(this.type), this.arguments);
	}

    }

    /*
	 * 
	 */

    public static enum WarningType {
	MISSING_TRANSLATION, MISSING_BUNDLE, TRANSLATION_TO_MUCH;
    }
}
